/**
 * @file BM77SSP03.c
 * @brief bluetooth Interface
 *
 * @version Fixed
 * @author lbx
 * @date 2014-05-04
 */
#include <sys/ioctl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "config.h"
#include "console.h"
#include "bt_cmd.h"
#include "device.h"

static bt_retfunc_t bt_retfunc = NULL;
static command_t *bt_cmd_list;
static int bt_list_cnt = 0;

void bt_retfunc_reg(bt_retfunc_t func)
{
    bt_retfunc = func;
}


void bt_retfunc_free(void)
{
    bt_retfunc = NULL;
}

int bt_cmd_reg(command_t *cmd_list, int list_cnt)
{
    if (cmd_list == NULL || list_cnt == 0)
        return -1;
    
    bt_cmd_list = cmd_list;
    bt_list_cnt = list_cnt;
    
    return 0;
}

int bt_cmd_return(uint8_t * buffer, size_t len)
{
	int ret;
	if (bt_retfunc != NULL) {
		ret = bt_retfunc(buffer, len);
		bt_retfunc = NULL;
		return ret;
	}
	else
		return 0;
}

enum ParseState {
        PS_WHITESPACE,
        PS_TOKEN,
        PS_STRING,
        PS_ESCAPE
};

static enum ParseState stackedState;
static void parseargs(char *argstr, int *argc_p, char **argv, char** resid)
{
        int argc = 0;
        char c;
        enum ParseState lastState = PS_WHITESPACE;

        /* tokenize the argstr */
        while ((c = *argstr) != 0) {
                enum ParseState newState;

                if (c == ';' && lastState != PS_STRING && lastState != PS_ESCAPE)
                        break;

                if (lastState == PS_ESCAPE) {
                        newState = stackedState;
                } else if (lastState == PS_STRING) {
                        if (c == '"') {
                                newState = PS_WHITESPACE;
                                *argstr = 0;
                        } else {
                                newState = PS_STRING;
                        }
                } else if ((c == ' ') || (c == '\t')) {
                        /* whitespace character */
                        *argstr = 0;
                        newState = PS_WHITESPACE;
                } else if (c == '"') {
                        newState = PS_STRING;
                        *argstr++ = 0;
                        argv[argc++] = argstr;
                } else if (c == '\\') {
                        stackedState = lastState;
                        newState = PS_ESCAPE;
                } else {
                        /* token */
                        if (lastState == PS_WHITESPACE) {
                                argv[argc++] = argstr;
                        }
                        newState = PS_TOKEN;
                }

                lastState = newState;
                argstr++;
        }

        argv[argc] = NULL;
        if (argc_p != NULL)
                *argc_p = argc;

        if (*argstr == ';') {
                *argstr++ = '\0';
        }
        *resid = argstr;
}

static command_t *find_cmd(const char *cmdname)
{
        command_t *cmd;
        int i;

        if (cmdname == NULL) return NULL;

        for (cmd = bt_cmd_list, i = 0; i < bt_list_cnt; cmd ++, i ++) {
                if (strcmp(cmd->name, cmdname) == 0) {
                        return cmd;
                }
        }
        
        return NULL;
}

static int exec_cmd(int argc, const char **argv)
{
        command_t *cmd = find_cmd(argv[0]);

        if (cmd == NULL) {
                return 0;
        }
        cmd->cmdfunc(argc, argv);
		return 1;
}

int handle_bt_at(char *argstr)
{
	int argc;
	char *argv[128];
	char *resid;

	memset(argv, 0, sizeof(argv));
	parseargs(argstr, &argc, argv, &resid);
	if (argc > 0) {
   		return exec_cmd(argc, (const char **)argv);
	}

	return 0;
}


